<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048数字拼图</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            color: white;
            overflow-x: hidden;
            padding: 20px;
        }
        
        .container {
            max-width: 500px;
            width: 100%;
            text-align: center;
        }
        
        h1 {
            font-size: 3rem;
            margin-bottom: 10px;
            text-shadow: 0 0 10px #ff9900, 0 0 20px #ff9900;
            letter-spacing: 2px;
            background: linear-gradient(to right, #ff9900, #ffff00);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        .subtitle {
            font-size: 1.1rem;
            margin-bottom: 15px;
            color: #ffcc80;
        }
        
        .game-info {
            display: flex;
            justify-content: space-between;
            margin: 15px 0;
            padding: 12px;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 10px;
            border: 1px solid #ff9900;
            flex-wrap: wrap;
        }
        
        .info-item {
            font-size: 1.1rem;
            font-weight: bold;
            text-shadow: 0 0 5px #ff9900;
            margin: 5px 0;
        }
        
        .game-container {
            position: relative;
            margin: 15px auto;
            border: 3px solid #ff9900;
            border-radius: 10px;
            box-shadow: 0 0 20px #ff9900, inset 0 0 20px rgba(255, 153, 0, 0.1);
            overflow: hidden;
            max-width: 450px;
            background: rgba(0, 0, 0, 0.3);
            padding: 15px;
        }
        
        .grid-container {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(4, 1fr);
            gap: 10px;
            width: 100%;
            aspect-ratio: 1/1;
            background: rgba(187, 173, 160, 0.3);
            border-radius: 6px;
            padding: 10px;
            position: relative;
        }
        
        .grid-cell {
            background: rgba(238, 228, 218, 0.35);
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.8rem;
            font-weight: bold;
            color: #776e65;
        }
        
        .tile {
            position: absolute;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.8rem;
            font-weight: bold;
            border-radius: 3px;
            transition: all 0.15s ease;
            z-index: 10;
        }
        
        .tile-2 { background: #eee4da; color: #776e65; }
        .tile-4 { background: #ede0c8; color: #776e65; }
        .tile-8 { background: #f2b179; color: white; }
        .tile-16 { background: #f59563; color: white; }
        .tile-32 { background: #f67c5f; color: white; }
        .tile-64 { background: #f65e3b; color: white; }
        .tile-128 { background: #edcf72; color: white; font-size: 1.5rem; }
        .tile-256 { background: #edcc61; color: white; font-size: 1.5rem; }
        .tile-512 { background: #edc850; color: white; font-size: 1.5rem; }
        .tile-1024 { background: #edc53f; color: white; font-size: 1.2rem; }
        .tile-2048 { background: #edc22e; color: white; font-size: 1.2rem; }
        
        .controls {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin: 15px 0;
            flex-wrap: wrap;
        }
        
        button {
            background: linear-gradient(135deg, #ff9900, #ffff00);
            border: none;
            padding: 10px 20px;
            font-size: 1rem;
            border-radius: 50px;
            cursor: pointer;
            color: #000;
            font-weight: bold;
            box-shadow: 0 0 15px rgba(255, 153, 0, 0.7);
            transition: all 0.3s ease;
            min-width: 120px;
        }
        
        button:hover {
            transform: translateY(-3px);
            box-shadow: 0 0 20px rgba(255, 153, 0, 0.9);
        }
        
        button:active {
            transform: translateY(1px);
        }
        
        button:disabled {
            background: #555;
            color: #888;
            box-shadow: none;
            cursor: not-allowed;
        }
        
        .instructions {
            margin-top: 20px;
            padding: 15px;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 10px;
            border: 1px solid #ff9900;
            max-width: 500px;
        }
        
        .instructions h3 {
            color: #ff9900;
            margin-bottom: 10px;
            font-size: 1.3rem;
        }
        
        .instructions p {
            margin: 8px 0;
            color: #ffcc80;
            font-size: 0.95rem;
            line-height: 1.4;
        }
        
        .game-over {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            padding: 25px;
            border-radius: 15px;
            border: 2px solid #ff0000;
            text-align: center;
            box-shadow: 0 0 30px #ff0000;
            z-index: 20;
            display: none;
            width: 85%;
            max-width: 350px;
        }
        
        .game-over h2 {
            font-size: 1.8rem;
            color: #ff0000;
            margin-bottom: 12px;
            text-shadow: 0 0 10px #ff0000;
        }
        
        .game-over p {
            font-size: 1.1rem;
            margin: 8px 0;
        }
        
        .win-message {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            padding: 25px;
            border-radius: 15px;
            border: 2px solid #00ff00;
            text-align: center;
            box-shadow: 0 0 30px #00ff00;
            z-index: 20;
            display: none;
            width: 85%;
            max-width: 350px;
        }
        
        .win-message h2 {
            font-size: 1.8rem;
            color: #00ff00;
            margin-bottom: 12px;
            text-shadow: 0 0 10px #00ff00;
        }
        
        .win-message p {
            font-size: 1.1rem;
            margin: 8px 0;
        }
        
        .mobile-controls {
            display: none;
            margin-top: 15px;
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: repeat(3, 1fr);
            gap: 8px;
            max-width: 180px;
        }
        
        .mobile-controls button {
            width: 55px;
            height: 55px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.3rem;
            padding: 0;
            min-width: auto;
        }
        
        .mobile-controls .up {
            grid-column: 2;
            grid-row: 1;
        }
        
        .mobile-controls .left {
            grid-column: 1;
            grid-row: 2;
        }
        
        .mobile-controls .right {
            grid-column: 3;
            grid-row: 2;
        }
        
        .mobile-controls .down {
            grid-column: 2;
            grid-row: 3;
        }
        
        @media (max-width: 600px) {
            h1 {
                font-size: 2.2rem;
            }
            
            .game-info {
                flex-direction: column;
                gap: 8px;
            }
            
            .controls {
                flex-direction: column;
                align-items: center;
                gap: 8px;
            }
            
            button {
                width: 100%;
                max-width: 220px;
                padding: 8px 15px;
            }
            
            .mobile-controls {
                display: grid;
            }
            
            .instructions {
                margin-top: 15px;
                padding: 12px;
            }
            
            .tile {
                font-size: 1.5rem;
            }
            
            .tile-128, .tile-256, .tile-512 {
                font-size: 1.2rem;
            }
            
            .tile-1024, .tile-2048 {
                font-size: 1rem;
            }
        }
        
        @media (max-width: 400px) {
            body {
                padding: 15px;
            }
            
            h1 {
                font-size: 1.8rem;
            }
            
            .subtitle {
                font-size: 0.95rem;
            }
            
            .game-container {
                margin: 10px auto;
                padding: 10px;
            }
            
            .controls {
                margin: 10px 0;
            }
            
            button {
                font-size: 0.9rem;
                padding: 7px 12px;
            }
            
            .grid-cell, .tile {
                font-size: 1.3rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>2048数字拼图</h1>
        <p class="subtitle">合并相同数字，挑战2048！</p>
        
        <div class="game-info">
            <div class="info-item">分数: <span id="score">0</span></div>
            <div class="info-item">步数: <span id="moves">0</span></div>
            <div class="info-item">最高分: <span id="best">0</span></div>
        </div>
        
        <div class="game-container">
            <div class="grid-container" id="grid">
                <!-- 网格将由JavaScript生成 -->
            </div>
            
            <div class="game-over" id="gameOver">
                <h2>游戏结束</h2>
                <p>你的最终分数: <span id="finalScore">0</span></p>
                <p id="gameMessage">再试一次，创造新纪录！</p>
                <button id="restartBtn">重新开始</button>
            </div>
            
            <div class="win-message" id="winMessage">
                <h2>恭喜你赢了！</h2>
                <p>你成功合成了2048！</p>
                <p>分数: <span id="winScore">0</span></p>
                <button id="continueBtn">继续游戏</button>
            </div>
        </div>
        
        <div class="mobile-controls">
            <button class="up">↑</button>
            <button class="left">←</button>
            <button class="right">→</button>
            <button class="down">↓</button>
        </div>
        
        <div class="controls">
            <button id="startBtn">开始游戏</button>
            <button id="undoBtn">撤销</button>
            <button id="hintBtn">提示</button>
        </div>
        
        <div class="instructions">
            <h3>游戏说明</h3>
            <p>使用方向键或屏幕按钮移动方块</p>
            <p>相同数字的方块相撞时会合并成为它们的和</p>
            <p>每次移动后会在空白处随机生成一个2或4的方块</p>
            <p>当棋盘被填满且无法移动时游戏结束</p>
            <p>成功合成2048即可获胜，但可以继续挑战更高分！</p>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const gridContainer = document.getElementById('grid');
            const startBtn = document.getElementById('startBtn');
            const undoBtn = document.getElementById('undoBtn');
            const hintBtn = document.getElementById('hintBtn');
            const restartBtn = document.getElementById('restartBtn');
            const continueBtn = document.getElementById('continueBtn');
            const scoreEl = document.getElementById('score');
            const movesEl = document.getElementById('moves');
            const bestEl = document.getElementById('best');
            const gameOverEl = document.getElementById('gameOver');
            const winMessageEl = document.getElementById('winMessage');
            const finalScoreEl = document.getElementById('finalScore');
            const winScoreEl = document.getElementById('winScore');
            const gameMessageEl = document.getElementById('gameMessage');
            
            // 移动控制按钮
            const upBtn = document.querySelector('.mobile-controls .up');
            const leftBtn = document.querySelector('.mobile-controls .left');
            const rightBtn = document.querySelector('.mobile-controls .right');
            const downBtn = document.querySelector('.mobile-controls .down');
            
            // 游戏状态
            let game = {
                grid: [],
                score: 0,
                moves: 0,
                best: localStorage.getItem('2048-best') || 0,
                gameOver: false,
                won: false,
                history: []
            };
            
            // 初始化游戏
            function initGame() {
                // 创建4x4网格
                game.grid = Array(4).fill().map(() => Array(4).fill(0));
                game.score = 0;
                game.moves = 0;
                game.gameOver = false;
                game.won = false;
                game.history = [];
                
                // 生成网格HTML
                gridContainer.innerHTML = '';
                for (let i = 0; i < 16; i++) {
                    const cell = document.createElement('div');
                    cell.className = 'grid-cell';
                    gridContainer.appendChild(cell);
                }
                
                // 添加两个初始方块
                addRandomTile();
                addRandomTile();
                
                updateUI();
                gameOverEl.style.display = 'none';
                winMessageEl.style.display = 'none';
                
                // 保存初始状态
                saveState();
                
                // 渲染方块
                renderTiles();
            }
            
            // 添加随机方块
            function addRandomTile() {
                const emptyCells = [];
                
                // 找到所有空格子
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (game.grid[i][j] === 0) {
                            emptyCells.push({x: i, y: j});
                        }
                    }
                }
                
                if (emptyCells.length > 0) {
                    // 随机选择一个空格子
                    const cell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    // 90%概率生成2，10%概率生成4
                    game.grid[cell.x][cell.y] = Math.random() < 0.9 ? 2 : 4;
                }
            }
            
            // 保存游戏状态
            function saveState() {
                game.history.push({
                    grid: JSON.parse(JSON.stringify(game.grid)),
                    score: game.score,
                    moves: game.moves
                });
                
                // 只保留最近10步的历史
                if (game.history.length > 10) {
                    game.history.shift();
                }
            }
            
            // 撤销上一步
            function undoMove() {
                if (game.history.length > 1) {
                    game.history.pop(); // 移除当前状态
                    const prevState = game.history[game.history.length - 1];
                    game.grid = JSON.parse(JSON.stringify(prevState.grid));
                    game.score = prevState.score;
                    game.moves = prevState.moves;
                    game.gameOver = false;
                    game.won = false;
                    
                    updateUI();
                    renderTiles();
                }
            }
            
            // 移动方块
            function move(direction) {
                if (game.gameOver) return;
                
                const prevGrid = JSON.parse(JSON.stringify(game.grid));
                let moved = false;
                
                // 根据方向处理移动
                switch (direction) {
                    case 'up':
                        moved = moveUp();
                        break;
                    case 'down':
                        moved = moveDown();
                        break;
                    case 'left':
                        moved = moveLeft();
                        break;
                    case 'right':
                        moved = moveRight();
                        break;
                }
                
                // 如果有移动，更新游戏状态
                if (moved) {
                    game.moves++;
                    addRandomTile();
                    saveState();
                    updateUI();
                    renderTiles();
                    
                    // 检查游戏是否结束
                    if (isGameOver()) {
                        game.gameOver = true;
                        finalScoreEl.textContent = game.score;
                        gameOverEl.style.display = 'block';
                    }
                    
                    // 检查是否获胜
                    if (!game.won && hasWon()) {
                        game.won = true;
                        winScoreEl.textContent = game.score;
                        winMessageEl.style.display = 'block';
                    }
                }
            }
            
            // 向上移动
            function moveUp() {
                let moved = false;
                
                for (let j = 0; j < 4; j++) {
                    for (let i = 1; i < 4; i++) {
                        if (game.grid[i][j] !== 0) {
                            let row = i;
                            while (row > 0 && game.grid[row - 1][j] === 0) {
                                game.grid[row - 1][j] = game.grid[row][j];
                                game.grid[row][j] = 0;
                                row--;
                                moved = true;
                            }
                            
                            if (row > 0 && game.grid[row - 1][j] === game.grid[row][j]) {
                                game.grid[row - 1][j] *= 2;
                                game.score += game.grid[row - 1][j];
                                game.grid[row][j] = 0;
                                moved = true;
                            }
                        }
                    }
                }
                
                return moved;
            }
            
            // 向下移动
            function moveDown() {
                let moved = false;
                
                for (let j = 0; j < 4; j++) {
                    for (let i = 2; i >= 0; i--) {
                        if (game.grid[i][j] !== 0) {
                            let row = i;
                            while (row < 3 && game.grid[row + 1][j] === 0) {
                                game.grid[row + 1][j] = game.grid[row][j];
                                game.grid[row][j] = 0;
                                row++;
                                moved = true;
                            }
                            
                            if (row < 3 && game.grid[row + 1][j] === game.grid[row][j]) {
                                game.grid[row + 1][j] *= 2;
                                game.score += game.grid[row + 1][j];
                                game.grid[row][j] = 0;
                                moved = true;
                            }
                        }
                    }
                }
                
                return moved;
            }
            
            // 向左移动
            function moveLeft() {
                let moved = false;
                
                for (let i = 0; i < 4; i++) {
                    for (let j = 1; j < 4; j++) {
                        if (game.grid[i][j] !== 0) {
                            let col = j;
                            while (col > 0 && game.grid[i][col - 1] === 0) {
                                game.grid[i][col - 1] = game.grid[i][col];
                                game.grid[i][col] = 0;
                                col--;
                                moved = true;
                            }
                            
                            if (col > 0 && game.grid[i][col - 1] === game.grid[i][col]) {
                                game.grid[i][col - 1] *= 2;
                                game.score += game.grid[i][col - 1];
                                game.grid[i][col] = 0;
                                moved = true;
                            }
                        }
                    }
                }
                
                return moved;
            }
            
            // 向右移动
            function moveRight() {
                let moved = false;
                
                for (let i = 0; i < 4; i++) {
                    for (let j = 2; j >= 0; j--) {
                        if (game.grid[i][j] !== 0) {
                            let col = j;
                            while (col < 3 && game.grid[i][col + 1] === 0) {
                                game.grid[i][col + 1] = game.grid[i][col];
                                game.grid[i][col] = 0;
                                col++;
                                moved = true;
                            }
                            
                            if (col < 3 && game.grid[i][col + 1] === game.grid[i][col]) {
                                game.grid[i][col + 1] *= 2;
                                game.score += game.grid[i][col + 1];
                                game.grid[i][col] = 0;
                                moved = true;
                            }
                        }
                    }
                }
                
                return moved;
            }
            
            // 检查游戏是否结束
            function isGameOver() {
                // 检查是否有空格子
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (game.grid[i][j] === 0) {
                            return false;
                        }
                    }
                }
                
                // 检查是否有可以合并的相邻格子
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        const value = game.grid[i][j];
                        if (
                            (i < 3 && game.grid[i + 1][j] === value) ||
                            (j < 3 && game.grid[i][j + 1] === value)
                        ) {
                            return false;
                        }
                    }
                }
                
                return true;
            }
            
            // 检查是否获胜
            function hasWon() {
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (game.grid[i][j] === 2048) {
                            return true;
                        }
                    }
                }
                return false;
            }
            
            // 渲染方块
            function renderTiles() {
                // 移除所有现有的方块
                const existingTiles = document.querySelectorAll('.tile');
                existingTiles.forEach(tile => tile.remove());
                
                // 获取网格容器的实际尺寸
                const containerWidth = gridContainer.offsetWidth;
                const containerHeight = gridContainer.offsetHeight;
                
                // 计算每个格子的实际尺寸
                const cellWidth = (containerWidth - 50) / 4; // 减去内边距和间隙
                const cellHeight = (containerHeight - 50) / 4;
                
                // 添加新的方块
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        const value = game.grid[i][j];
                        if (value !== 0) {
                            const tile = document.createElement('div');
                            tile.className = `tile tile-${value}`;
                            tile.textContent = value;
                            
                            // 使用像素精确定位
                            const left = 10 + j * (cellWidth + 10);
                            const top = 10 + i * (cellHeight + 10);
                            
                            tile.style.left = `${left}px`;
                            tile.style.top = `${top}px`;
                            tile.style.width = `${cellWidth}px`;
                            tile.style.height = `${cellHeight}px`;
                            
                            gridContainer.appendChild(tile);
                        }
                    }
                }
            }
            
            // 更新UI
            function updateUI() {
                scoreEl.textContent = game.score;
                movesEl.textContent = game.moves;
                
                // 更新最高分
                if (game.score > game.best) {
                    game.best = game.score;
                    localStorage.setItem('2048-best', game.best);
                }
                bestEl.textContent = game.best;
            }
            
            // 事件监听
            window.addEventListener('keydown', (e) => {
                if (game.gameOver && !game.won) return;
                
                switch (e.key) {
                    case 'ArrowUp':
                        e.preventDefault();
                        move('up');
                        break;
                    case 'ArrowDown':
                        e.preventDefault();
                        move('down');
                        break;
                    case 'ArrowLeft':
                        e.preventDefault();
                        move('left');
                        break;
                    case 'ArrowRight':
                        e.preventDefault();
                        move('right');
                        break;
                }
            });
            
            // 移动控制按钮事件
            upBtn.addEventListener('click', () => move('up'));
            downBtn.addEventListener('click', () => move('down'));
            leftBtn.addEventListener('click', () => move('left'));
            rightBtn.addEventListener('click', () => move('right'));
            
            // 控制按钮事件
            startBtn.addEventListener('click', () => {
                initGame();
            });
            
            undoBtn.addEventListener('click', () => {
                undoMove();
            });
            
            hintBtn.addEventListener('click', () => {
                alert('提示：尽量保持最大数字在角落，按顺序合并小数字！');
            });
            
            restartBtn.addEventListener('click', () => {
                initGame();
            });
            
            continueBtn.addEventListener('click', () => {
                winMessageEl.style.display = 'none';
            });
            
            // 窗口大小改变时重新渲染
            window.addEventListener('resize', () => {
                if (game.grid && game.grid.length > 0) {
                    renderTiles();
                }
            });
            
            // 初始化游戏
            initGame();
        });
    </script>
</body>
</html>